using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using XNALibrary.Game;

namespace XNALibrary.PostProcessing
{
    public class PostProcessingManager
    {
        //Lista de pasadas
        private SpriteBatch sprite;
        private Texture2D SceneRender;
        private List<BaseFilter> filters;

        #region Properties
        public List<BaseFilter> Filters
        {
            get { return filters; }
            set { filters = value; }
        }

        #endregion
	
        //Constructor
        public PostProcessingManager()
        {
            filters = new List<BaseFilter>();
            SceneRender = new Texture2D(BaseGame.device,
                                        BaseGame.device.Viewport.Width,
                                        BaseGame.device.Viewport.Height, 
                                        1,
                                        ResourceUsage.ResolveTarget,
                                        BaseGame.device.PresentationParameters.BackBufferFormat,
                                        ResourceManagementMode.Manual);

            sprite = new SpriteBatch(BaseGame.device);

        }

        public void AddFilter(BaseFilter newFilter)
        {
            newFilter.RenderTarget = new RenderTarget2D(BaseGame.device,
                                              BaseGame.device.Viewport.Width,
                                              BaseGame.device.Viewport.Height,
                                              1,
                                              BaseGame.device.DisplayMode.Format);
            newFilter.Owner = this;
            newFilter.Register();
            filters.Add(newFilter);
        }

        //
        // Aplica iterativamente uno a uno todos los filtros
        //
        public void PostRender()
        {
            //Dibuja la imagen original
            BaseGame.device.ResolveBackBuffer(SceneRender);

            int t;
            for (int i = 0; i < filters.Count-1; i++)
            {
                //Asigna como resultado del filtro el renderTarget del propio filtro
                BaseGame.device.SetRenderTarget(0, filters[i].RenderTarget);
                //Actualizamos el filtro
                filters[i].Update();
                //Para resolver la textura de entrada del filtro
                // 0 Imagen original
                // 1 Primer filtro
                // 2 Segundo filtro 
                // ...
                t = filters[i].Texture;
                if (t == 0)
                    filters[0].DrawFilter(SceneRender, filters[i].Shader, sprite);
                else
                    filters[i].DrawFilter(filters[t - 1].RenderTarget.GetTexture(), filters[i].Shader, sprite);

                //Dibuja la imagen filtrada
                BaseGame.device.ResolveRenderTarget(0);
            }

            //Como es el ultimo filtro asignamos como salida la salida estandar
            BaseGame.device.SetRenderTarget(0, null);

            //Actualizamos el filtro
            filters[filters.Count - 1].Update();
            //Al igual que antes para resolver la textura de entrada del filtro
            // 0 Imagen original
            // 1 Primer filtro
            // 2 Segundo filtro 
            // ...
            t = filters[filters.Count - 1].Texture;
            if (t == 0)
                filters[0].DrawFilter(SceneRender, filters[filters.Count - 1].Shader, sprite);
            else
                filters[t].DrawFilter(filters[t - 1].RenderTarget.GetTexture(), filters[t].Shader, sprite);
        }

        //
        //Le aplica el effect a texture y lo dibuja en el sprite
        //
        private void DrawQuad(Texture2D texture, Effect effect)
        {
            effect.Begin();
            sprite.Begin(SpriteBlendMode.None, SpriteSortMode.Immediate, SaveStateMode.SaveState);

            foreach (EffectPass pass in effect.CurrentTechnique.Passes)
            {
                pass.Begin();
                sprite.Draw(texture, Vector2.Zero, Color.White);
                pass.End();
            }
            sprite.End();
            effect.End();
        }

    }
}
